<template>
    <div class="demo1">

        <!--    画布    -->
        <div class="panel" id="g6" ref="g6">
            <!--    工具栏    -->
            <div class="custom-node-area" ref="itemPanel">
                <div class="icon-tool">
                    <i draggable="true"
                       data-label="开始环节"
                       data-shape="circle-node"
                       class="node iconfont icon-circle"/>
                    <i draggable="true"
                       data-label="审核环节"
                       data-shape="rect-node"
                       class="node iconfont icon-rect"/>
                    <i draggable="true"
                       data-label="椭圆形节点"
                       data-shape="ellipse-node"
                       class="node iconfont icon-ellipse"/>
                    <i draggable="true"
                       data-label="网关"
                       data-shape="diamond-node"
                       class="node iconfont icon-diamond"/>
                </div>
            </div>
            <!--       minimap     -->
            <div class="mini-map" id="miniMap">
            </div>
        </div>
        <div>
            <el-button @click="save">保存</el-button>
        </div>
    </div>
</template>

<script>
import G6 from '@antv/g6'
import registerFactory from './components/graph/graph';

export default {
    name: "index",
    data() {
        return {
            graph: null
        }
    }
    ,
    methods: {
        //初始画画布
        createGraphic(success) {
            const vm = this;
            const grid = new G6.Grid();
            const menu = new G6.Menu({
                offsetX: -20,
                offsetY: -50,
                itemTypes: ['node', 'edge'],
                getContent(e) {
                    const outDiv = document.createElement('div');

                    outDiv.style.width = '80px';
                    outDiv.style.cursor = 'pointer';
                    outDiv.innerHTML = '<p id="deleteNode">删除节点</p>';
                    return outDiv;
                },
                handleMenuClick(target, item) {
                    const {id} = target;

                    if (id) {
                        vm[id](item);
                    }
                },
            });
            const minimap = new G6.Minimap({
                container: document.getElementById("miniMap"),
                size: [300, 200],
            });
            const cfg = registerFactory(G6, {
                container: 'g6',
                // renderer: 'svg',
                // 所有节点默认配置
                defaultNode: {
                    type: 'rect-node',
                    style: {
                        radius: 10,
                        width: 100,
                        height: 50,
                        cursor: 'move',
                        fill: '#ecf3ff',
                    },
                    labelCfg: {
                        fontSize: 20,
                        style: {
                            cursor: 'move',
                        },
                    },
                },
                // 所有边的默认配置
                defaultEdge: {
                    type: 'polyline', // 扩展了内置边, 有边的事件
                    style: {
                        radius: 5,
                        offset: 15,
                        stroke: '#aab7c3',
                        lineAppendWidth: 10, // 防止线太细没法点中
                        endArrow: true,
                        startAngle: true,
                    },
                },
                // 覆盖全局样式
                nodeStateStyles: {
                    'nodeState:default': {
                        opacity: 1,
                    },
                    'nodeState:hover': {
                        opacity: 0.8,
                    },
                    'nodeState:selected': {
                        opacity: 0.9,
                    },
                },
                // 默认边不同状态下的样式集合
                edgeStateStyles: {
                    'edgeState:default': {
                        stroke: '#aab7c3',
                    },
                    'edgeState:selected': {
                        stroke: '#1890FF',
                    },
                    'edgeState:hover': {
                        animate: true,
                        animationType: 'dash',
                        stroke: '#1890FF',
                    },
                },
                modes: {
                    // 支持的 behavior
                    default: ['drag-canvas', 'drag-shadow-node', 'canvas-event', 'delete-item', 'select-node', 'hover-node', 'active-edge'],
                    originDrag: ['drag-canvas', 'drag-node', 'canvas-event', 'delete-item', 'select-node', 'hover-node', 'active-edge'],
                },
                plugins: [menu, minimap, grid],
                // ... 其他G6原生入参
            });

            this.graph = new G6.Graph(cfg);
            success();
        },
        // 初始化图事件
        initGraphEvent() {
            this.graph.on('drop', e => {
                const {originalEvent} = e;

                if (originalEvent.dataTransfer) {
                    const transferData = originalEvent.dataTransfer.getData('dragComponent');

                    if (transferData) {
                        this.addNode(transferData, e);
                    }
                }
            });

            this.graph.on('node:drop', e => {
                e.item.getOutEdges().forEach(edge => {
                    edge.clearStates('edgeState');
                });
            });

            this.graph.on('after-node-selected', e => {
                this.configVisible = !!e;

                if (e && e.item) {
                    const model = e.item.get('model');

                    this.config = model;
                    this.label = model.label;
                    this.labelCfg = {
                        fontSize: model.labelCfg.fontSize,
                        style: {
                            fill: model.labelCfg.style.fill,
                        },
                    };
                    this.node = {
                        fill: model.style.fill,
                        borderColor: model.style.stroke,
                        lineDash: model.style.lineDash || 'none',
                        width: model.style.width,
                        height: model.style.height,
                        shape: model.type,
                    };
                }
            });

            this.graph.on('on-node-mouseenter', e => {
                if (e && e.item) {
                    e.item.getOutEdges().forEach(edge => {
                        edge.clearStates('edgeState');
                        edge.setState('edgeState', 'hover');
                    });
                }
            });

            // 鼠标拖拽到画布外时特殊处理
            this.graph.on('mousedown', e => {
                this.isMouseDown = true;
            });
            this.graph.on('mouseup', e => {
                this.isMouseDown = false;
            });
            this.graph.on('canvas:mouseleave', e => {
                this.graph.getNodes().forEach(x => {
                    const group = x.getContainer();

                    group.clearAnchor();
                    x.clearStates('anchorActived');
                });
            });

            this.graph.on('on-node-mousemove', e => {
                if (e && e.item) {
                    this.tooltip = e.item.get('model').id;
                    this.left = e.clientX + 40;
                    this.top = e.clientY - 20;
                }
            });

            this.graph.on('on-node-mouseleave', e => {
                if (e && e.item) {
                    this.tooltip = '';
                    if (e && e.item) {
                        e.item.getOutEdges().forEach(edge => {
                            edge.clearStates('edgeState');
                        });
                    }
                }
            });

            this.graph.on('before-node-removed', ({target, callback}) => {
                console.log(target);
                setTimeout(() => {
                    // 确认提示
                    callback(true);
                }, 1000);
            });

            this.graph.on('after-node-dblclick', e => {
                if (e && e.item) {
                    console.log(e.item);
                    alert("双击了")
                }
            });

            this.graph.on('after-edge-selected', e => {
                this.configVisible = !!e;

                if (e && e.item) {
                    this.config = e.item.get('model').id;

                    this.graph.updateItem(e.item, {
                        // shape: 'line-edge',
                        style: {
                            radius: 10,
                            lineWidth: 2,
                        },
                    });
                }
            });

            this.graph.on('on-edge-mousemove', e => {
                if (e && e.item) {
                    this.tooltip = e.item.get('model').label;
                    this.left = e.clientX + 40;
                    this.top = e.clientY - 20;
                }
            });

            this.graph.on('on-edge-mouseleave', e => {
                if (e && e.item) {
                    this.tooltip = '';
                }
            });

            this.graph.on('before-edge-add', ({source, target, sourceAnchor, targetAnchor}) => {
                setTimeout(() => {
                    this.graph.addItem('edge', {
                        id: `${+new Date() + (Math.random() * 10000).toFixed(0)}`, // edge id
                        source: source.get('id'),
                        target: target.get('id'),
                        sourceAnchor,
                        targetAnchor,
                        // label:  'edge label',
                    });
                }, 100);
            });
        },
        //初始化工具栏
        initToolbar() {
            const icons = [...this.$refs.itemPanel.querySelector('.icon-tool').querySelectorAll('.node')];

            icons.forEach(icon => {
                icon.addEventListener('dragstart', event => {
                    const shape = icon.getAttribute('data-shape');
                    const label = icon.getAttribute('data-label');
                    const fill = icon.getAttribute('fill');
                    /* 设置拖拽传输数据 */
                    event.dataTransfer.setData('dragComponent',
                        JSON.stringify({
                            label,
                            shape,
                            fill,
                        }),
                    );
                });
            });

            // 阻止默认动作
            document.addEventListener('drop', e => {
                e.preventDefault();
            }, false);
        },
        addNode(transferData, {x, y}) {
            const {label, shape, fill} = JSON.parse(transferData);

            const model = {
                label,
                // id:  Util.uniqueId(),
                // 形状
                type: shape,
                style: {
                    fill: fill || '#ecf3ff',
                },
                // 坐标
                x,
                y,
            };

            this.graph.addItem('node', model);
        },
        deleteNode(item) {
            this.graph.removeItem(item);
        },

        save() {
            let graphJson = this.graph.save()
            graphJson.nodes.forEach(node => {
                delete node.style
                delete node.labelCfg
            })
            graphJson.edges.forEach(edge => {
                delete edge.style
            })
            console.log(JSON.stringify(graphJson))
        }
    },
    mounted() {
        const data = {
            nodes: [
                {
                    id: 'node1',
                    label: 'node1',
                },
                {
                    id: 'node2',
                    label: 'node2',
                },
            ],
            edges: [
                {
                    source: 'node1',
                    target: 'node2',
                },
            ],
        }

        this.$nextTick(() => {
            this.initToolbar()
            this.createGraphic(() => {
                this.graph.read(data)
            })
            this.initGraphEvent()
        })
    }
}
</script>

<style scoped lang="less">
.demo1 {
    width: 100%;
    height: 100%;
}

.custom-node-area {
    //height: 100px;
    position: absolute;
    top: 0px;
    left: 0px;
    padding: 20px;
    background-color: #dcdfe6;
    opacity: 0.6;
}

.panel {
    height: calc(100% - 200px);
    position: relative;
}

.icon-tool {
    i {
        font-size: 40px;
    }
}

.mini-map {
    position: absolute;
    bottom: 15px;
    right: 15px;
    width: 300px;
    height: 200px;
    background-color: #fff;
    //border: 1px solid #ccc;
    //padding: 20px;
    //background-color: #dcdfe6;
}
</style>